package com.ruoyi.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.ruoyi.order.config.FileConfig;
import com.ruoyi.order.domain.DTO.VerificationResult;
import com.ruoyi.order.domain.Orders;
import com.ruoyi.order.domain.VO.VerificationDetail;
import com.ruoyi.order.domain.VerificationRecord;
import com.ruoyi.order.mapper.OrdersMapper;
import com.ruoyi.order.mapper.VerificationRecordMapper;
import com.ruoyi.order.service.IVerificationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerificationServiceImpl extends ServiceImpl<VerificationRecordMapper, VerificationRecord> implements IVerificationService {

    @Autowired
    private VerificationRecordMapper verificationRecordMapper;

    @Autowired
    private OrdersMapper ordersMapper;


    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private FileConfig  fileConfig;

    /** 核销码有效期   30天 */
    public static final int VERIFY_CODE_EXPIRE_HOURS = 720;


    /** 核销码长度 */
    public static final int VERIFY_CODE_LENGTH = 10;

    @Override
    @Transactional
    public VerificationRecord generateVerificationRecord(Long orderId, Long merchantId, Long userId) {
        // 验证订单是否存在
        Orders order = ordersMapper.selectOrdersByOId(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }

        // 检查是否已生成核销码
        VerificationRecord existVerifyRecord = verificationRecordMapper.selectByOrderIdAndMerchantIdAndUserId(orderId, merchantId,userId);
        if (existVerifyRecord != null) {
            throw new RuntimeException("核销码已经存在，不得重复创建");
        }

        // 生成核销码和二维码
        String verifyCode = generateUniqueVerifyCode();
        String qrCodePath = null;
        try {
            qrCodePath = generateQRCode(verifyCode);
        } catch (Exception e) {
            log.error("生成二维码失败", e);
            throw new RuntimeException("生成核销二维码失败");
        }

        // 计算过期时间
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        calendar.add(Calendar.HOUR, VERIFY_CODE_EXPIRE_HOURS);
        Date expireTime = calendar.getTime();



        // 创建核销记录
        VerificationRecord record = new VerificationRecord();
        record.setOrderId(orderId);
        record.setUserId(order.getUserId());
        record.setVerifyCode(verifyCode);
        record.setMerchantId(merchantId);
        record.setVerifyExpireTime(expireTime);
        record.setCreateTime(now);
        record.setStatus(0); // 待核销状态
        record.setQrCodePath(qrCodePath);

        // 插入核销表
        verificationRecordMapper.insertRecord(record);

        // 更新订单状态
        Orders orders = new Orders();
        orders.setOrderId(orderId);

        orders.setOrderStatus(4L); // 待核销状态
        orders.setVerifyCode(verifyCode);
//        orders.setAppointTime(expireTime);
        ordersMapper.updateOrders(orders);

        // 缓存核销码信息
        redisTemplate.opsForValue().set(
                "verify:code:" + verifyCode,
                record,
                VERIFY_CODE_EXPIRE_HOURS,
                TimeUnit.HOURS
        );

        return record;
    }


    @Override
    @Transactional
    public VerificationResult verifyOrder(String verifyCode, Long merchantId) {
        VerificationResult result = new VerificationResult();

        // 1. 获取核销记录
        VerificationRecord record = getVerificationRecord(verifyCode);
        if (record == null) {
            return buildFailedResult(result, "核销码不存在");
        }

        // 2. 验证核销码状态
        if (record.getStatus() == 1) {
            return buildFailedResult(result, "该核销码已使用");
        }
        if (record.getStatus() == 2) {
            return buildFailedResult(result, "该核销码已过期");
        }

        // 3. 验证核销码有效性
        if (!isVerifyCodeValid(record)) {
            // 更新状态为过期
            updateRecordStatus(record.getVerifyId(), 2);
            return buildFailedResult(result, "核销码已过期");
        }

        // 4. 验证商家权限
        if (merchantId!= record.getMerchantId()) {
            return buildFailedResult(result, "无权核销该订单");
        }

        // 5. 验证订单状态
        Orders order = ordersMapper.selectOrdersByOId(record.getOrderId());
        if (order == null || order.getOrderStatus() != 4L) { // 4表示待核销状态
            return buildFailedResult(result, "订单状态异常");
        }

        // 6. 执行核销
        try {
            Date now = new Date();

            // 更新订单状态
            order.setOrderStatus(1L); // 1表示订单完成
            order.setVerifyTime(now);
            ordersMapper.updateOrders(order);

            // 更新核销记录
            record.setVerifyTime(now);
            record.setStatus(1); // 已核销状态
            verificationRecordMapper.updateRecord(record);

            // 从缓存中删除
            redisTemplate.delete("verify:code:" + verifyCode);

            // 构建成功结果
            result.setSuccess(true);
            result.setMessage("核销成功");
            result.setOrderId(order.getOrderId());
            result.setVerifyTime(now);
            return result;
        } catch (Exception e) {
            log.error("核销操作失败", e);
            throw new RuntimeException("核销操作失败", e);
        }
    }

    // 更新记录状态
    private void updateRecordStatus(Long verifyId, int status) {
        VerificationRecord record = new VerificationRecord();
        record.setVerifyId(verifyId);
        record.setStatus(status);
        verificationRecordMapper.updateRecord(record);
    }

    /**
     * 查询核销列表
     */
    public List<VerificationDetail> selectList() {
        return   verificationRecordMapper.selectDetail();
    }


    /**
     * 内部方法
     */

    private VerificationRecord getVerificationRecord(String verifyCode) {
        // 先从缓存获取
        VerificationRecord record = (VerificationRecord) redisTemplate.opsForValue().get("verify:code:" + verifyCode);
        if (record == null) {
            // 缓存未命中，从数据库查询
            record = verificationRecordMapper.selectByVerifyCode(verifyCode);
            if (record != null) {
                // 重新放入缓存
                redisTemplate.opsForValue().set(
                        "verify:code:" + verifyCode,
                        record,
                        calculateRemainingTime(record.getVerifyExpireTime()),
                        TimeUnit.SECONDS
                );
            }
        }
        return record;
    }

    private boolean isVerifyCodeValid(VerificationRecord record) {
        Orders orders = ordersMapper.selectOrdersByOId(record.getOrderId());
        // 检查过期时间
        Date now = new Date();
        return record.getVerifyExpireTime() != null && now.before(record.getVerifyExpireTime())
        ||(record.getVerifyExpireTime().before(orders.getAppointTime()));
    }




    private long calculateRemainingTime(Date expireTime) {
        if (expireTime == null) {
            return VERIFY_CODE_EXPIRE_HOURS * 60 * 60L;
        }
        return (expireTime.getTime() - System.currentTimeMillis()) / 1000;
    }

    private String generateRandomCode(int length) {
        String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        return sb.toString();



    }


    /**
     * 生成二维码
     */
    private String generateQRCode(String verifyCode) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(verifyCode, BarcodeFormat.QR_CODE, 300, 300);

        // 生成文件名
        String fileName = "qr_" + verifyCode + "_" + System.currentTimeMillis() + ".png";
        Path path = Paths.get(fileConfig.getQrCodePath(), fileName);

        // 写入文件
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);

        return path.toString();
    }

    // 生成唯一核销码
    private String generateUniqueVerifyCode() {
        String code;
        int retryCount = 0;
        final int maxRetry = 5;

        do {
            code = generateRandomCode(VERIFY_CODE_LENGTH); // 固定10位
            retryCount++;

            // 防止无限循环
            if (retryCount > maxRetry) {
                throw new RuntimeException("生成唯一核销码失败");
            }
        } while (verificationRecordMapper.existsByVerifyCode(code));

        return code;
    }




    private VerificationResult buildFailedResult(VerificationResult result, String message) {
        result.setSuccess(false);
        result.setMessage(message);
        return result;
    }



}